package cn.mulanbay.log.web.aop;

import cn.mulanbay.api.system.bean.RemoteRoleUrlAuthRequest;
import cn.mulanbay.api.system.service.RemoteRoleService;
import cn.mulanbay.business.handler.FeignCheckHandler;
import cn.mulanbay.common.config.CacheKey;
import cn.mulanbay.common.exception.ApplicationException;
import cn.mulanbay.common.exception.ErrorCode;
import cn.mulanbay.common.util.StringUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局Aop
 * 登录、权限验证及用户信息的自动注入
 *
 * @author fenghong
 * @create 2022-01-16 10:00
 */
@Component
@Aspect
public class ControllerHandler {

    private static final Logger logger = LoggerFactory.getLogger(ControllerHandler.class);

    @Autowired
    FeignCheckHandler feignCheckHandler;

    @Autowired
    RemoteRoleService remoteRoleService;

    private HttpServletRequest getRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes()).getRequest();
        return request;
    }

    /**
     * controller包的子包里面任何方法
     */
    @Pointcut("execution(public * cn.mulanbay.log.web.controller.*.*(..))")
    public void setUserInfo() {
    }

    /**
     * controller包的子包里面任何方法
     */
    @Pointcut("execution(public * cn.mulanbay.log.web.controller.*.*(..))")
    public void doLog() {
    }

    @Before("setUserInfo()")
    public void beforeBuss(JoinPoint joinPoint) {
        try {
            HttpServletRequest request = this.getRequest();
            String url = request.getServletPath();
            String method = request.getMethod();
            logger.debug("aop拦截："+url);
            //roleId由网关设置
            String rs = request.getHeader(CacheKey.DETAILS_ROLE_ID);
            if(StringUtil.isEmpty(rs)) {
                //feign内部调用
                int code = feignCheckHandler.checkFeignAuth(request);
                logger.debug("Feign内部鉴权结果,code:{}",code);
                if (code != ErrorCode.SUCCESS) {
                    throw new ApplicationException(code);
                }else {
                    return;
                }
            }
            Long roleId = Long.valueOf(rs);
            RemoteRoleUrlAuthRequest uar = new RemoteRoleUrlAuthRequest();
            uar.setRoleId(roleId);
            uar.setUrl(url);
            uar.setMethod(method);
            int resCode = remoteRoleService.isUrlAuth(uar).getData();
            logger.debug("role:{},url:{},method:{} 鉴权结果,resCode:{}",roleId,url,method,resCode);
            if(resCode!=ErrorCode.SUCCESS){
                throw new ApplicationException(resCode);
            }
        } catch (ApplicationException e) {
            throw e;
        } catch (Exception e) {
            logger.error("do beforeBuss error", e);
            throw new ApplicationException(ErrorCode.SYSTEM_ERROR,e.getMessage());
        }
    }

    @AfterReturning(value = "doLog()", returning = "resultMap")
    public void afterBuss(JoinPoint joinpoint, Object resultMap) {
    }

    //抛出异常时才调用
    @AfterThrowing("doLog()")
    public void afterThrowing() {
        //System.out.println("校验token出现异常了......");
    }

}
